/*
 * @(#)NotificationDAO.java 创建于 2016-07-16 13:09:36
 *
 * 版权：版权所有 Bsoft 保留所有权力。
 */
package com.bsoft.gol.hcs.common.dao;

import ctd.persistence.annotation.DAOMethod;
import ctd.persistence.annotation.DAOParam;
import ctd.persistence.support.hibernate.HibernateSupportDelegateDAO;
import ctd.persistence.support.hibernate.template.AbstractHibernateStatelessResultAction;
import ctd.persistence.support.hibernate.template.HibernateSessionTemplate;
import ctd.persistence.support.hibernate.template.HibernateStatelessResultAction;
import ctd.util.converter.ConversionUtils;
import hcn.base.Affair;
import hcn.base.Device;
import hcn.base.Notification;
import org.hibernate.Query;
import org.hibernate.StatelessSession;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.transform.Transformers;
import com.bsoft.gol.hcs.utils.CommonUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author <a href="mailto:chinnsii@163.com">zhengshi</a>
 */
public abstract class NotificationDAO extends HibernateSupportDelegateDAO<Device> {

    public NotificationDAO() {
        this.setKeyField("notificationId");
    }

    @DAOMethod(sql = "update Notification set status='1' where  userId=:userId and roleId=:roleId and notificationType=:notificationType and tenantId=:tenantId and status='0' ")
    public abstract void updateReadFlagByNotificationType(@DAOParam("userId") String userId, @DAOParam("roleId") String roleId, @DAOParam("notificationType") String notificationType, @DAOParam("tenantId") String tenantId);

    @DAOMethod(sql = "update Notification set status='1' where notificationId=:notificationId")
    public abstract void updateReadFlag(@DAOParam("notificationId") int notificationId);

    @DAOMethod(sql = "from Notification where  tenantId=:tenantId and userId=:userId and roleId=:roleId and notificationType=:notificationType and status <> '2' order by sendTime desc")
    public abstract List<Notification> findAllNotificationsByNotificationType(@DAOParam("tenantId") String tenantId, @DAOParam("userId") String userId, @DAOParam("roleId") String roleId, @DAOParam("notificationType") String notificationType, @DAOParam(pageStart = true) int start, @DAOParam(pageLimit = true) int limit);

    @DAOMethod(sql = "update Notification set status='2' where tenantId=:tenantId and userId=:userId and roleId=:roleId and notificationType=:notificationType", params = {@DAOParam(name = "tenantId", value = "%$tenantId", dataType = "string")})
    public abstract void deleteNotifications(@DAOParam("userId") String userId, @DAOParam("roleId") String roleId, @DAOParam("notificationType") String notificationType);

    @DAOMethod(sql = "update Notification set status='2' where notificationId=:notificationId")
    public abstract void deleteNotification(@DAOParam("notificationId") int notificationId);

    @DAOMethod(sql = "update Notification set status='2' where tenantId=:tenantId and userId=:userId and roleId=:roleId and notificationType=:notificationType")
    public abstract void deleteAllNotificationByType(@DAOParam("userId") String userId, @DAOParam("roleId") String roleId, @DAOParam("notificationType") String notificationType, @DAOParam("tenantId") String tenantId);

    /**
     * 大类分组。
     *
     * @param userId
     * @param roleId
     * @param status
     * @return
     */
    public List<Map<String, Object>> getNotificationGroupCount(final String tenantId, final String userId, final String roleId, final String status) {
        final HibernateStatelessResultAction<List<Map<String, Object>>> action = new AbstractHibernateStatelessResultAction<List<Map<String, Object>>>() {
            @Override
            @SuppressWarnings("unchecked")
            public void execute(StatelessSession ss) throws Exception {
                String hql = "select notificationType as notificationType, count(*) as count from Notification" +
                        " where tenantId=:tenantId and userId=:userId and roleId=:roleId and status=:status group by notificationType ";
                //排序去掉，只能端按照时间再排序，后台dm不支持标准sql，实现不了 目前这一的返回结构
                //" where tenantId=:tenantId and userId=:userId and roleId=:roleId and status=:status group by notificationType order by sendTime desc ";
                Query query = ss.createQuery(hql);
                query = query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
                query.setString("tenantId", tenantId);
                query.setString("userId", userId);
                query.setString("roleId", roleId);
                query.setString("status", status);
                List<Map<String, Object>> list = (query.list());
                setResult(list);
            }
        };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    public List<Map<String, Object>> updateReadFlagByMInNotificationType(final String userId,final String roleId, final String notificationType, final String businessType,final String tenantId,final String visitOrganization) {
        final HibernateStatelessResultAction<List<Map<String, Object>>> action = new AbstractHibernateStatelessResultAction<List<Map<String, Object>>>() {
            @Override
            @SuppressWarnings("unchecked")
            public void execute(StatelessSession ss) throws Exception {
                StringBuffer stringBuffer = new StringBuffer();
                stringBuffer.append(" update Notification set status='1'  " );
                stringBuffer.append(" where  userId=:userId and roleId=:roleId and notificationType=:notificationType and businessType=:businessType and tenantId=:tenantId and status='0'  ");
                if(CommonUtils.isNotEmpty(visitOrganization)){
                    stringBuffer.append(" and extras like '%\"localOrgId\":\""+visitOrganization+"\"%' ");
                }
                Query query = ss.createQuery(stringBuffer.toString());
                query.setString("userId", userId);
                query.setString("roleId", roleId);
                query.setString("notificationType", notificationType);
                query.setString("businessType", businessType);
                query.setString("tenantId", tenantId);
                query.executeUpdate();
            }
        };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    /**
     * 小类分组。
     *
     * @param userId
     * @param roleId
     * @param status
     * @return
     */
    public List<Map<String, Object>> getMinNotificationGroupCount(final String tenantId, final String userId, final String roleId, final String status,final String visitOrganization) {
        final HibernateStatelessResultAction<List<Map<String, Object>>> action = new AbstractHibernateStatelessResultAction<List<Map<String, Object>>>() {
            @Override
            @SuppressWarnings("unchecked")
            public void execute(StatelessSession ss) throws Exception {
                StringBuffer stringBuffer = new StringBuffer();
                stringBuffer.append("select businessType as businessType, count(*) as count from Notification " );
                stringBuffer.append(" where tenantId=:tenantId and userId=:userId and roleId=:roleId and status=:status ");
                if(CommonUtils.isNotEmpty(visitOrganization)){
                    stringBuffer.append(" and extras like '%\"localOrgId\":\""+visitOrganization+"\"%' ");
                }
                stringBuffer.append(" group by businessType ");
                Query query = ss.createQuery(stringBuffer.toString());
                query = query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
                query.setString("tenantId", tenantId);
                query.setString("userId", userId);
                query.setString("roleId", roleId);
                query.setString("status", status);
                List<Map<String, Object>> list = (query.list());
                setResult(list);
            }
        };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    /**
     * 查询当前用户所有消息大类
     *
     * @param userId
     * @param roleId
     * @return
     */
    public List<String> getMessageTypes(final String tenantId, final String userId, final String roleId) {
        final HibernateStatelessResultAction<List<String>> action = new AbstractHibernateStatelessResultAction<List<String>>() {
            @Override
            @SuppressWarnings("unchecked")
            public void execute(StatelessSession ss) throws Exception {
                String hql = "select distinct notificationType from Notification where tenantId=:tenantId and userId=:userId and roleId=:roleId and status<>:status";
                Query query = ss.createQuery(hql);
                query.setString("tenantId", tenantId);
                query.setString("userId", userId);
                query.setString("roleId", roleId);
                query.setString("status", "2");
                List<String> list = (query.list());
                setResult(list);
            }
        };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    public List<Notification> getLastBusinessNotifications(final String tenantId, final String userId, final String roleId) {
        HibernateStatelessResultAction<List<Notification>> action = new AbstractHibernateStatelessResultAction<List<Notification>>() {
            @Override
            @SuppressWarnings("unchecked")
            public void execute(StatelessSession ss) throws Exception {
                Query query = ss.createSQLQuery("select a.* from base_notification a ,(select max(notificationId) notificationId from base_notification " +
                        "where tenantId=:tenantId and userId=:userId and roleId=:roleId and status<>:status group by businessType) b  where a.notificationId=b.notificationId ORDER BY a.notificationId DESC");
                query.setString("tenantId", tenantId);
                query.setString("userId", userId);
                query.setString("roleId", roleId);
                query.setString("status", "2");
                query.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
                List<Map> list = (List<Map>)query.list();
                List<Notification> notifications = new ArrayList<>();
                if(null!=list&&list.size()>0){
                    for (Map map : list) {
                        Notification notification = ConversionUtils.convert(map, Notification.class);
                        notifications.add(notification);
                    }
                }
                setResult(notifications);
            }
        };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    /**
     * @param affairType
     * @param businessKey
     * @param notification
     * @return
     */
    private Affair createAffair(String tenantId, String affairType, long businessKey, Notification notification) {
        Affair affair = new Affair();
        affair.setAffairType(affairType);
        affair.setBusinessKey(businessKey);
        affair.setTenantId(tenantId);
        affair.setBusinessType(notification.getBusinessType());
        affair.setDealFlag("0");
        affair.setUserId(notification.getUserId());
        affair.setRoleId(notification.getRoleId());
        affair.setNotificationId(notification.getNotificationId());
        return affair;
    }
}
